import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:async';
import 'dart:io';

class News extends StatefulWidget {
  const News({Key key, this.data}) : super(key: key); //构造函数中增加参数
  final String data; //为参数分配空间
  @override
  _MyTabbedPageState createState() => _MyTabbedPageState();
}

//定义TAB页对象，这样做的好处就是，可以灵活定义每个tab页用到的对象，可结合Iterable对象使用，以后讲
class NewsTab {
  String text;
  NewsList newsList;
  NewsTab(this.text, this.newsList);
}

class _MyTabbedPageState extends State<News>
    with SingleTickerProviderStateMixin {
  //将每个Tab页都结构化处理下，由于http的请求需要传入新闻类型的参数，因此将新闻类型参数值作为对象属性传入Tab中
  final List<NewsTab> myTabs = <NewsTab>[
    NewsTab('头条', NewsList(newsType: 'toutiao')), //拼音就是参数值
    NewsTab('社会', NewsList(newsType: 'shehui')),
    NewsTab('国内', NewsList(newsType: 'guonei')),
    NewsTab('国际', NewsList(newsType: 'guoji')),
    NewsTab('娱乐', NewsList(newsType: 'yule')),
    NewsTab('体育', NewsList(newsType: 'tiyu')),
    NewsTab('军事', NewsList(newsType: 'junshi')),
    NewsTab('科技', NewsList(newsType: 'keji')),
    NewsTab('财经', NewsList(newsType: 'caijing')),
    NewsTab('时尚', NewsList(newsType: 'shishang')),
  ];

  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(vsync: this, length: myTabs.length);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.orangeAccent,
        title: TabBar(
          controller: _tabController,
          tabs: myTabs.map((NewsTab item) {
            // NewsTab可以不用声明
            return Tab(text: item.text ?? '错误');
          }).toList(),
          indicatorColor: Colors.white,
          // 水平滚动的开关，开启后Tab标签可自适应宽度并可横向拉动，关闭后每个Tab自动压缩为总长符合屏幕宽度的等宽，默认关闭
          isScrollable: true,
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: myTabs.map((item) {
          return item.newsList; //使用参数值
        }).toList(),
      ),
    );
  }
}

//新闻列表
class NewsList extends StatefulWidget {
  final String newsType; //新闻类型
  @override
  NewsList({Key key, this.newsType}) : super(key: key);

  _NewsListState createState() => _NewsListState();
}

class _NewsListState extends State<NewsList> {
  final String _url = 'http://v.juhe.cn/toutiao/index?';
  List data;

  //HTTP请求的函数返回值为异步控件Future
  Future<String> get(String category) async {
    var httpClient = HttpClient();
    var request = await httpClient.getUrl(Uri.parse(
        '${_url}type=$category&key=3a86f36bd3ecac8a51135ded5eebe862'));
    var response = await request.close();
    return await response.transform(utf8.decoder).join();
  }

  Future<Null> loadData() async {
    await get(widget.newsType); //注意await关键字
    if (!mounted) return; //异步处理，防止报错
    setState(() {}); //什么都不做，只为触发RefreshIndicator的子控件刷新
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      child: FutureBuilder(
        //用于懒加载的FutureBuilder对象
        future: get(widget.newsType), //HTTP请求获取数据，将被AsyncSnapshot对象监视
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none: //get未执行时
            case ConnectionState.waiting: //get正在执行时
              return Center(
                child: Card(
                  child: Text('loading...'), //在页面中央显示正在加载
                ),
              );
            default:
              if (snapshot.hasError) //get执行完成但出现异常
                return Text('Error: ${snapshot.error}');
              else //get正常执行完成
                // 创建列表，列表数据来源于snapshot的返回值，而snapshot就是get(widget.newsType)执行完毕时的快照
                // get(widget.newsType)执行完毕时的快照即函数最后的返回值。
                return createListView(context, snapshot);
          }
        },
      ),
      onRefresh: loadData,
    );
  }

  Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
    // print(snapshot.data);
    List values;
    values = jsonDecode(snapshot.data)['result'] != null
        ? jsonDecode(snapshot.data)['result']['data']
        : [''];
    switch (values.length) {
      case 1: //没有获取到数据，则返回请求失败的原因
        return Center(
          child: Card(
            child: Text(jsonDecode(snapshot.data)['reason']),
          ),
        );
      default:
        return ListView.builder(
            physics: const AlwaysScrollableScrollPhysics(),
            padding: const EdgeInsets.all(16.0),
            // itemCount: data == null ? 0 : data.length,
            itemCount: values == null ? 0 : values.length,
            itemBuilder: (context, i) {
              // return _newsRow(data[i]);//把数据项塞入ListView中
              return _newsRow(values[i]);
            });
    }
  }

  //新闻列表单个item
  Widget _newsRow(newsInfo) {
    return Card(
      child: Column(
        children: <Widget>[
          Container(
            child: ListTile(
              title: Text(
                newsInfo["title"],
                textScaleFactor: 1.5,
              ),
            ),
            margin: EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0),
          ),
          _generateItem(newsInfo), //根据图片数量返回对应样式的图片
          Container(
              padding: const EdgeInsets.fromLTRB(25.0, 10.0, 0.0, 10.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Expanded(
                    child: Text(newsInfo["author_name"]),
                  ),
                  Expanded(
                    child: Text(newsInfo["date"]),
                  ),
                ],
              )),
        ],
      ),
    );
  }

  //根据获取到的图片数量控制图片的显示样式
  _generateItem(Map newsInfo) {
    if (newsInfo["thumbnail_pic_s"] != null &&
        newsInfo["thumbnail_pic_s02"] != null &&
        newsInfo["thumbnail_pic_s03"] != null) {
      return _generateThreePicItem(newsInfo);
    } else {
      return _generateOnePicItem(newsInfo);
    }
  }

  //仅有一个图片时的效果
  _generateOnePicItem(Map newsInfo) {
    return Row(
      mainAxisSize: MainAxisSize.max,
      children: <Widget>[
        Expanded(
            child: Container(
                padding: const EdgeInsets.all(3.0),
                child: SizedBox(
                  child: Image.network(
                    newsInfo['thumbnail_pic_s'],
                    fit: BoxFit.fitWidth,
                  ),
                  height: 200.0,
                )))
      ],
    );
  }

  //有三张图片时的效果
  _generateThreePicItem(Map newsInfo) {
    return Row(
      children: <Widget>[
        Expanded(
            child: Container(
                padding: const EdgeInsets.all(4.0),
                child: Image.network(newsInfo['thumbnail_pic_s']))),
        Expanded(
            child: Container(
                padding: const EdgeInsets.all(4.0),
                child: Image.network(newsInfo['thumbnail_pic_s02']))),
        Expanded(
            child: Container(
                padding: const EdgeInsets.all(4.0),
                child: Image.network(newsInfo['thumbnail_pic_s03'])))
      ],
    );
  }
}
